package ar.edu.utn.frba.dds.opendesigners.resultados;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

//import ar.edu.utn.frba.dds.opendesigners.connectingFlights.Tramo;
import ar.edu.utn.frba.dds.opendesigners.excepciones.ExcepcionAsientoInvalido;
import ar.edu.utn.frba.dds.opendesigners.resultados.orden.CriterioOrden;
import ar.edu.utn.frba.dds.opendesigners.resultados.orden.OrdenPorPopularidad;
import ar.edu.utn.frba.dds.opendesigners.resultados.orden.OrdenPorPrecio;
import ar.edu.utn.frba.dds.opendesigners.resultados.orden.OrdenPorPrecioReverso;
import ar.edu.utn.frba.dds.opendesigners.resultados.orden.OrdenPorTiempoDeVuelo;

//Los resultados que se reciban de las aerolineas, tanto sea con escalas o sin, deben implementar esta interface
public class ResultadoBusqueda{
	//Implementa una lista de objetos Asiento.
	private List<Asiento> listaResultado = new ArrayList<Asiento>();

	public ResultadoBusqueda() {
		
	}
	
	public void agregarItem(Asiento item) {
		this.listaResultado.add(item);
	}
	
	public ResultadoBusqueda agregarListaItems(List<Asiento> listaItems){
		this.listaResultado.addAll(listaItems);
		return this;
	}

	public void agregarResultadoBusqueda(ResultadoBusqueda resultadoBusqueda) {
		this.listaResultado.addAll(resultadoBusqueda.getListaResultados());
	}

	public List<Asiento> getListaResultados(){
		return this.listaResultado;
	}
	
	//Como LANCHITA devuelve cualquier verdura a pesar de que le paso los parametros correctos de origen y fin
	//Hay que usar este filtro para asegurarse...
	public List<Asiento> filtrarPor(String origen, String destino){
		ArrayList<Asiento> copyList = new ArrayList<Asiento>(this.listaResultado);
		for (Asiento item : this.listaResultado) {
			if (origen != null && destino != null){
				if (!item.getOrigen().equals(origen) || !item.getDestino().equals(destino)){
					copyList.remove(item);
				}
			}
			else{

				if ((origen != null && !item.getOrigen().equals(origen)) || (destino != null && !item.getOrigen().equals(origen))){
						copyList.remove(item);
				}
			}
			
		}
		this.listaResultado = copyList;
		
		return this.listaResultado;
	}
	public List<Asiento> filtrarPor(BigDecimal precio) {
		ArrayList<Asiento> copyList = new ArrayList<Asiento>(this.listaResultado);
		for (Asiento item : this.listaResultado) {
			if (item.precioMayorQue(precio))
				copyList.remove(item);
		}
		this.listaResultado = copyList;
		
		return this.listaResultado;
	}

	public List<Asiento> filtrarPorRangoDe(BigDecimal precioMinimo, BigDecimal precioMaximo){
		
		//Onda, JAVA SUCKS en aritmetica
		//Esto significa "si minPrice > 0 y minPrice < maxPrice". Oh Dios! bring back .NET! 
		if (precioMinimo.compareTo(BigDecimal.valueOf(0)) == 1 && precioMinimo.compareTo(precioMaximo) == -1){
			ArrayList<Asiento> copyList = new ArrayList<Asiento>(this.listaResultado);
			for (Asiento route : this.listaResultado) {
				if (route.precioMayorQue(precioMaximo) || route.precioMenorQue(precioMinimo)){
					copyList.remove(route);
				}
			}
			this.listaResultado = copyList;
		}
		
		return this.listaResultado;
	}
	
	public List<Asiento> filtrarPor(boolean estadoDeReserva){
		
		if (!estadoDeReserva) { //Si NO quiero incluir los reservados, los saco
			
			ArrayList<Asiento> copyList = new ArrayList<Asiento>(this.listaResultado);
			for (Asiento item : this.listaResultado) {
				
				if (String.valueOf(item.getEstado()).equals("R")){ //Si esta reservado...
					copyList.remove(item);
				}
			}
			
			this.listaResultado = copyList;
		}
	
		return this.listaResultado;
	}
	
	public  List<Asiento> filtrarPor(ArrayList<String> tipoDeAsiento){
		ArrayList<Asiento> copyList = new ArrayList<Asiento>(this.listaResultado);
		
		//Para cada tipo de asiento en el resultado,
		if (!tipoDeAsiento.isEmpty()){
			//Si era vacio no se cambia
			for(String seatType : tipoDeAsiento){
				for (Asiento item : this.listaResultado) {
					if (String.valueOf(item.getTipo()) == seatType){
						copyList.add(item);
					}
				}
			}
			
			this.listaResultado = copyList;
		}
	
		return this.listaResultado;
	}
		
	public List<Asiento> agregarRecargo(BigDecimal recargo) {
		
		for (Asiento asiento : this.listaResultado) {
            asiento.sumarPrecio(recargo);
	    }
	    return this.listaResultado;
	}
	
	
	public Asiento seleccionarPor(String numeroVuelo, String numeroAsiento) {
		for (Asiento item : this.listaResultado) {
			if (item.getNumeroVuelo().equals(numeroVuelo)
					&& item.getNumeroAsiento().equals(numeroAsiento))
				return item;
		}
		throw new ExcepcionAsientoInvalido();
	}

	public Asiento seleccionarPor(int position) {
		return this.listaResultado.get(position);
	}

	public List<Asiento> listadoDeAsientos() {
		return this.listaResultado;
	}

	/*
	public boolean equals(ItinearioDirecto search) {
		return this.listadoDeAsientos().equals(search.listadoDeAsientos());
	}
	
	public String toString() {
		String toString = new String();
		for (ResultadoBusquedaItem item : this.listaResultado) {
			toString = toString.concat(item.toString());
		}
		return toString;
	}
	*/
	//Ordena según algún criterio y devuelve la lista resultante
	public List<Asiento> ordenarPor(CriterioOrden criterioOrden){
		
		 
		switch(criterioOrden){
			case PRICE_ASC:
			{
				Collections.sort(this.listaResultado, new OrdenPorPrecio());
				break;
			}
			case FLIGHT_TIME:
			{
				Collections.sort(this.listaResultado, new OrdenPorTiempoDeVuelo());
				break;
			}
			case POPULARITY:
			{
				Collections.sort(this.listaResultado, new OrdenPorPopularidad());
				break;
			}
			case PRICE_DSC:
			default: 
			{
				Collections.sort(this.listaResultado, new OrdenPorPrecioReverso());
				break;
			}
		}
		
		return this.listaResultado;
	}
	
	/**
	 *  el estado de la respuesta de la busqueda
	 * @return
	 * 		En caso de estar vacio, devuelve true
	 */
	public boolean esVacio(){
		return this.listaResultado.isEmpty();
	}
	
	/**
	 *  Cantidad de asientos
	 * @return
	 * 		Cantidad de la respuesta de la busqueda
	 */
	public int cantidadAsientos(){
		return this.listaResultado.size();
	}
	
	private List<Asiento> getVuelosSaliendoDe(String origen){
		List<Asiento> subLista = new ArrayList<Asiento>();
		
		//Recorro y agregando lo que cumplen
		for (Asiento item : this.getListaResultados()){
			if (item.getOrigen().equals(origen)){
				subLista.add(item);
			}
		}
		
		return subLista;
	}
	
	public ResultadoBusqueda getAsientosConOrigenDe(String origen){
		List<Asiento> listaAsientosConCriterio = this.getVuelosSaliendoDe(origen);
		return new ResultadoBusqueda().agregarListaItems(listaAsientosConCriterio);
	}
	
	private List<Asiento> getVuelosLlegandoDe(String destino){
		List<Asiento> subLista = new ArrayList<Asiento>();
		
		//Recorro y agregando lo que cumplen
		for (Asiento item : this.getListaResultados()){
			if (item.getDestino().equals(destino)){
				subLista.add(item);
			}
		}
		
		return subLista;
	}
	
	public ResultadoBusqueda getAsientosConDestinoA(String destino){
		List<Asiento> listaAsientosConCriterio = this.getVuelosLlegandoDe(destino);
		return new ResultadoBusqueda().agregarListaItems(listaAsientosConCriterio);
	}
	
	private List<Asiento> getVuelosSaliendoLlegandoA(String origen, String destino){
		List<Asiento> subLista = new ArrayList<Asiento>();
		
		//Recorro y agregando lo que cumplen
		for (Asiento item : this.getListaResultados()){
			if ((item.getOrigen().equals(origen) && item.getDestino().equals(destino))){
				subLista.add(item);
			}
		}
		
		return subLista;
	}
	
	public ResultadoBusqueda getVuelosSaliendoDeLlegandoA(String origen, String destino){
		List<Asiento> listaAsientosConCriterio = this.getVuelosSaliendoLlegandoA(origen, destino);
		return new ResultadoBusqueda().agregarListaItems(listaAsientosConCriterio);
	}
}

